package com.tonggedata.dataapi.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import io.swagger.annotations.Api;
import org.apache.dolphinscheduler.api.utils.PageInfo;

import org.springframework.stereotype.Service;
import cn.hutool.core.bean.BeanUtil;

import com.tonggedata.dataapi.entity.ApiConfig;
import com.tonggedata.dataapi.service.ApiConfigService;
import com.tonggedata.dataapi.mapper.ApiConfigMapper;
import com.tonggedata.dataapi.dto.ApiConfigDto;
import com.tonggedata.dataapi.dto.ApiConfigParamDto;
import com.tonggedata.dataapi.util.ApiServiceUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;

import org.apache.dolphinscheduler.api.enums.Status;
import org.apache.dolphinscheduler.api.utils.Result;
import org.apache.dolphinscheduler.common.Constants;
import org.apache.dolphinscheduler.dao.entity.User;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import cn.hutool.core.util.StrUtil;

import java.util.*;

/**
 * ==================================================
 *
 * @author : tonggedata
 * @fileName:
 * @create : 2022-06-19 13:08:46
 * @Description： api配置表，api核心
 * ==================================================
 * @since 1.0.0
 */
@Service
public class ApiConfigServiceImpl extends ServiceImpl<ApiConfigMapper, ApiConfig> implements ApiConfigService {


    private static final Logger logger = LoggerFactory.getLogger(ApiConfigServiceImpl.class);

    @Autowired
    private ApiConfigMapper apiConfigMapper;

    @Override
    public Map<String, Object> queryApiConfig(long id) {
        Map<String, Object> result = new HashMap<>();
        ApiConfig apiConfig = getById(id);
        if (apiConfig == null) {
//            putMsg(result, Status.RESOURCE_NOT_EXIST);
            return result;
        }
        // type
        ApiConfigDto apiConfigDto = new ApiConfigDto();
        BeanUtil.copyProperties(apiConfig, apiConfigDto);

        result.put(Constants.DATA_LIST, apiConfigDto);
        ApiServiceUtil.putMsg(result, Status.SUCCESS);
        return result;
    }


    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public Result<Object> delete(User loginUser, long id) {
        Result<Object> result = new Result<>();
        try {
            //query datasource by id
            ApiConfig apiConfig = getById(id);
            if (apiConfig == null) {
                logger.error("resource id {} not exist" , id);
                ApiServiceUtil.putMsg(result, Status.RESOURCE_NOT_EXIST);
                return result;
            }
            if (!ApiServiceUtil.hasPerm(loginUser, apiConfig.getCreateUser())) {
                ApiServiceUtil.putMsg(result, Status.USER_NO_OPERATION_PERM);
                return result;
            }
            apiConfigMapper.deleteById(id);
            ApiServiceUtil.putMsg(result, Status.SUCCESS);
        } catch (Exception e) {
            logger.error("delete apiConfig error" , e);
            throw new RuntimeException("delete apiConfig error" );
        }
        return result;
    }

    @Override
    public Result queryApiConfigListPaging(User loginUser, String searchVal, Integer pageNo, Integer pageSize) {
        Result result = new Result();
        Page<ApiConfig> apiConfigPage = new Page<>(pageNo, pageSize);
        LambdaQueryWrapper<ApiConfig> lambdaQuery = new LambdaQueryWrapper<ApiConfig>();
        if (!ApiServiceUtil.isAdmin(loginUser)) {
            lambdaQuery.eq(ApiConfig::getCreateUser, loginUser.getUserName());
        }
        if (StrUtil.isNotEmpty(searchVal)) {
            //lambdaQuery.eq(ApiConfig::getName, searchVal);
        }
        IPage<ApiConfig> ipage = page(apiConfigPage, lambdaQuery);
        //转换格式
        PageInfo<ApiConfig> pageInfo = new PageInfo<>(pageNo, pageSize);
        pageInfo.setTotal((int) ipage.getTotal());
        pageInfo.setTotalList(ipage.getRecords());
        result.setData(pageInfo);
        ApiServiceUtil.putMsg(result, Status.SUCCESS);
        return result;
    }

    @Override
    public Result queryApiConfigListByGroupId(User loginUser,Long groupId) {
        Result result = new Result();

        LambdaQueryWrapper<ApiConfig> lambdaQuery = new LambdaQueryWrapper<ApiConfig>();

        if (!ApiServiceUtil.isAdmin(loginUser)) {
            lambdaQuery.eq(ApiConfig::getCreateUser, loginUser.getUserName());
        }
        if (groupId>0) {
            lambdaQuery.eq(ApiConfig::getApiGroupId, groupId);
        }
        List<ApiConfig> apiConfigList = apiConfigMapper.selectList(lambdaQuery);

        List<ApiConfigDto> apiConfigDtos = new ArrayList<>();
        for (ApiConfig apiConfig : apiConfigList) {
            ApiConfigDto apiConfigDto = new ApiConfigDto();
            apiConfigDto.set(apiConfig);
            apiConfigDtos.add(apiConfigDto);
        }
        result.setData(apiConfigDtos);
//        ApiServiceUtil.putMsg(result, Status.SUCCESS);

        return result;
    }

    @Override
    public Map<String, Object> queryApiConfigList(User loginUser, String name) {
        Map<String, Object> result = new HashMap<>();

        LambdaQueryWrapper<ApiConfig> lambdaQuery = new LambdaQueryWrapper<ApiConfig>();

        if (!ApiServiceUtil.isAdmin(loginUser)) {
            lambdaQuery.eq(ApiConfig::getCreateUser, loginUser.getUserName());
        }
        if (StrUtil.isNotEmpty(name)) {
            lambdaQuery.like(ApiConfig::getName, name);
        }
        List<ApiConfig> apiConfigList = apiConfigMapper.selectList(lambdaQuery);

        result.put(Constants.DATA_LIST, apiConfigList);
        ApiServiceUtil.putMsg(result, Status.SUCCESS);

        return result;
    }


    @Override
    public Result<Object> updateApiConfig(long id, User loginUser, ApiConfigParamDto apiConfigParam) {
        //ApiConfigUtil.checkApiConfigParam(apiConfigParam);
        Result<Object> result = new Result<>();
        ApiConfig apiConfig = getById(id);
        if (apiConfig == null) {
            // putMsg(result, Status.RESOURCE_NOT_EXIST);
            return result;
        }

        if (!ApiServiceUtil.hasPerm(loginUser, apiConfig.getCreateUser())) {
            ApiServiceUtil.putMsg(result, Status.USER_NO_OPERATION_PERM);
            return result;
        }

        //check name can use or not
        if (!apiConfig.getName().trim().equals(apiConfig.getName()) && checkName(apiConfig.getName())) {
            //putMsg(result, Status.DATASOURCE_EXIST);
            return result;
        }

        BeanUtil.copyProperties(apiConfigParam, apiConfig, CopyOptions.create().setIgnoreNullValue(true));
        try {
            apiConfig.setUpdateTime(new Date());
            apiConfig.setUpdateUser(loginUser.getUserName());
            apiConfigMapper.updateById(apiConfig);
            ApiServiceUtil.putMsg(result, Status.SUCCESS);
        } catch (DuplicateKeyException ex) {
            logger.error("Update apiConfig error." , ex);
            ApiServiceUtil.putMsg(result, Status.DATASOURCE_EXIST);
        }
        return result;
    }

    private boolean checkName(String name) {
        LambdaQueryWrapper<ApiConfig> lambdaQuery = new LambdaQueryWrapper<ApiConfig>();
        lambdaQuery.eq(ApiConfig::getName, name);
        List<ApiConfig> apiConfigList = apiConfigMapper.selectList(lambdaQuery);
        return apiConfigList != null && !apiConfigList.isEmpty();
    }

    @Override
    public Result<Object> createApiConfig(User loginUser, ApiConfigDto apiConfigDto) {
        //DatasourceUtil.checkApiConfigParam(apiConfigParam);
        Result<Object> result = new Result<>();
        // check name can use or not
      /* if (checkName(apiConfigParam.getName())) {
            putMsg(result, Status.DATA_API_GROUP_ERROR);
            return result;
        }*/

        // build apiConfig
        ApiConfig apiConfig = new ApiConfig();
        Date now = new Date();


        //apiConfig.setCreateUser(loginUser.getUserName());
        BeanUtil.copyProperties(apiConfigDto, apiConfig, CopyOptions.create().setIgnoreNullValue(true));

        //apiConfig.setCreateTime(now);
        apiConfig.setUpdateTime(now);
        try {
            apiConfigMapper.insert(apiConfig);
            ApiServiceUtil.putMsg(result, Status.SUCCESS);
        } catch (DuplicateKeyException ex) {
            logger.error("Create apiConfig error." , ex);
            ApiServiceUtil.putMsg(result, Status.DATA_API_GROUP_ERROR);
        }

        return result;
    }

}
